import 'dart:convert';
import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:hj_crm/http/http_exception.dart';
import 'package:hj_crm/http/request_api.dart';
import 'package:hj_crm/log/logger.dart';
import 'package:hj_crm/utils/sp_utils.dart';

/// 连接超时时间
const Duration _connectTimeout = Duration(milliseconds: 10000);

/// 接受超时时间
const Duration _receiveTimeout = Duration(milliseconds: 10000);

/// 接受超时时间
const Duration _sendTimeout = Duration(milliseconds: 10000);

typedef Success<T> = Function(T data);

typedef Fail = Function(dynamic code, String msg);

class HttpRequest {
  ///是否携带token校验
  // static const String _token = '';

  ///全局Dio对象
  static Dio? _dio;

  /// 创建 dio 实例对象
  static Dio createInstance() {
    /// 全局属性：请求前缀、连接超时时间、响应超时时间
    var options = BaseOptions(
      /// 不使用http状态码判断状态，使用AdapterInterceptor来处理（适用于标准REST风格）
      validateStatus: (status) => true,
      baseUrl: RequestApi.baseUrl,
      sendTimeout: _sendTimeout,
      connectTimeout: _connectTimeout,
      receiveTimeout: _receiveTimeout,
    );
    _dio = Dio(options);
    return _dio!;
  }

  /// 请求，返回参数为 T
  /// [method]：请求方法，Method.POST等
  /// [path]：请求地址
  /// [params]：请求参数
  /// [success]：请求成功回调
  /// [fail]：请求失败回调
  /// [isJson]：是否json格式
  /// [token] 请求头是否携带token， 除了图形验证码及登录接口，其他接口都需要携带token
  /// [isLogin] 是否是登录请求，登录请求头不需要携带token，需要username及loginType
  /// [cancelToken] 取消请求token
  static Future request<T>(
    Method method,
    String path,
    dynamic params, {
    String? baseUrl,
    String? loginType,
    CancelToken? cancelToken,
    bool isJson = false,
    bool token = true,
    bool isLogin = false,
    Success<T>? success,
    Fail? fail,
  }) async {
    try {
      ///请求前先检查网络连接
      // var connectivityResult = await (Connectivity().checkConnectivity());
      // if (connectivityResult == ConnectivityResult.none) {
      //   _onError(HttpException.netError, '网络异常，请检查你的网络！', fail!);
      //   return;
      // }
      _dio ??= createInstance();
      _dio!.options.contentType =
          isJson ? Headers.jsonContentType : Headers.formUrlEncodedContentType;
      if (baseUrl != null) {
        _dio!.options.baseUrl = baseUrl;
      }
      Response response = await _dio!.request(path,
          data: params,
          cancelToken: cancelToken,
          queryParameters: params is Map == true ? params : null,
          options: Options(
            method: _methodValues[method],
            headers: isLogin
                ? _headerUsername(loginType, params['username'])
                : (token ? _headerToken(loginType) : null),
          ));

      if (response.data != null) {
        logger.d(response.data);
        success?.call(response.data!);
      }
    } on DioException catch (e) {
      if (CancelToken.isCancel(e)) {
        debugPrint('=============== Request canceled: ${e.message}');
      } else {
        final NetError netError = HttpException.handleException(e);
        _onError(netError.code, netError.msg, fail!);
        debugPrint("异常=====>$e");
      }
    }
  }
}

/// 此请求头用于获取token
Map<String, dynamic> _headerUsername(String? loginType, String? username) {
  /// 自定义Header,如需要添加token信息请调用此参数
  Map<String, dynamic> httpHeaders = {
    "Accept": "application/json, text/plain, */*",
    "Content-Type": "application/json",
  };
  httpHeaders.putIfAbsent('logintype', () => loginType);
  httpHeaders.putIfAbsent('username', () => username);
  return httpHeaders;
}

/// 需要携带token的请求头
Map<String, dynamic> _headerToken(String? loginType) {
  /// 自定义Header,如需要添加token信息请调用此参数
  Map<String, dynamic> httpHeaders = {
    "Accept": "application/json, text/plain, */*",
    "Content-Type": "application/json",
  };

  httpHeaders.putIfAbsent('logintype', () => loginType);

  String? token = SpUtil.getToken();
  if (token == null) {
    httpHeaders.putIfAbsent('Authorization',
        () => 'Basic MTM3ODYxODg2MDYxMzE0NDU3NjprMnF3c2sxNTMzZm1jMGhqdHJiYWowcjk=');
    return httpHeaders;
  }
  httpHeaders.putIfAbsent('Authorization', () => 'Bearer $token');

  return httpHeaders;
}

/// 错误回调
/// [code] 错误代码
/// [msg] 错误信息
/// [fail] 错误回调
void _onError(int code, String msg, Fail fail) {
  if (code == 0) {
    code = HttpException.unknownError;
    msg = '未知异常';
  }
  fail(code, msg);
}

///解析json数据
///[data] 数据
Map<String, dynamic> parseData(String data) {
  return json.decode(data) as Map<String, dynamic>;
}

///请求类型枚举
// ignore: constant_identifier_names
enum Method { GET, POST, DELETE, PUT, PATCH, HEAD }

///请求类型值
const _methodValues = {
  Method.GET: "get",
  Method.POST: "post",
  Method.DELETE: "delete",
  Method.PUT: "put",
  Method.PATCH: "patch",
  Method.HEAD: "head",
};
